package com.example.pluginmanager.config;


import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

@Configuration
public class RedisConfig {


    /**自定义RedisTemplate的数据类型
     *  主要配置的就是序列化机制
     *  更改它的序列化器为Json格式的序列化机制
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory){

        /*定义方法的返回值,泛型自动匹配，后面的可以省略*/
        RedisTemplate<String,Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);

        /*1.创建Jackson工具对象*/
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        /*2.为创建的工具对象设置Object映射*/
        jackson2JsonRedisSerializer.setObjectMapper(om);

        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.setHashValueSerializer(jackson2JsonRedisSerializer);

        /*将key与hashKey设置为String的序列化方式*/
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        template.setKeySerializer(stringRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);

        template.afterPropertiesSet();
        return template;
    }
    /**自定义RedisCacheManager来实现缓存管理器
     *  RedisTemplate采用我们自己配置的Bean组件
     */
    @Bean
    public RedisCacheManager UserRedisCacheManager(RedisConnectionFactory redisConnectionFactory){
        /**对于新版本的redis而言，它的RedisCacheManager创建与旧版相比发生了一定的变化。
         *  这里定制了这个序列化格式：
         *  serializeKeysWith(RedisSerializationContext.
         *      SerializationPair.fromSerializer(new StringRedisSerializer()))
         *  serializeValuesWith(RedisSerializationContext.
         *      SerializationPair.fromSerializer(new Jackson2JsonRedisSerializer<>(User.class)));
         *  这里则是设置生成的键值对的过期时间（作为缓存确实得有过期时间）
         *  entryTtl(Duration.ofSeconds(120))
         *  这里是禁止插入空值的键值对
         *  disableCachingNullValues()
         */
        RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(120))
                .disableCachingNullValues()
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new Jackson2JsonRedisSerializer<>(Object.class)));

        return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(cacheConfiguration).build();

    }
}

